package com.zwh.modules.goods.service;

import java.sql.Wrapper;
import java.util.Date;
import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.HashOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.zwh.common.data.redis.RedisUtil;
import com.zwh.common.idgen.IdGenerate;
import com.zwh.modules.datamax.entity.DataMax;
import com.zwh.modules.goods.constants.SecondKillConstatns;
import com.zwh.modules.goods.dao.GoodsDao;
import com.zwh.modules.goods.entity.Goods;
import com.baomidou.mybatisplus.extension.service.IService;
import com.zwh.modules.goods.rabbitmq.UserBuyGoodsMessage;
import com.zwh.modules.order.entity.Order;
import com.zwh.modules.order.service.OrderService;

/**
 * <p>
 *  服务类
 * </p>
 *
 * @author zhangwenhe
 * @since 2020-10-27
 */
@Service
public class GoodsService extends ServiceImpl<GoodsDao,Goods> {

    @Autowired
    private RedisTemplate<String, Object> redisTemplate;
    @Autowired
    private OrderService orderService;

    public void submitOrder(String seckillId) {
        //从缓存中查询秒杀商品
        Goods seckillGoods =(Goods)
                redisTemplate.boundHashOps("seckillGoods").get(seckillId);

        if(seckillGoods==null){
            throw new RuntimeException("商品不存在");
        }
        if(seckillGoods.getStockSum()<=0){
            throw new RuntimeException("商品已抢购一空");
        }
        //扣减（redis）库存
        seckillGoods.setStockSum(seckillGoods.getStockSum()-1);
        redisTemplate.boundHashOps("seckillGoods").put(seckillId, seckillGoods);//放回缓存
        if(seckillGoods.getStockSum()==0){//如果已经被秒光
            this.updateById(seckillGoods);//同步到数据库
            redisTemplate.boundHashOps("seckillGoods").delete(seckillId);
        }
        //保存（redis）订单
        String orderId = IdGenerate.nextId();
        Order seckillOrder=new Order();
        seckillOrder.setId(orderId);
        seckillOrder.setCreateDate(new Date());
        seckillOrder.setMoney(seckillGoods.getGoodsPrice());//秒杀价格
        seckillOrder.setGoodsId(seckillId);
        seckillOrder.setDeleteStatus("0");//状态
        redisTemplate.boundHashOps("seckillOrder").put(seckillId, seckillOrder);
    }


    /**
     * 验证码校验
     * @param userId
     * @param goodsId
     * @param verifyCode
     * @return
     */
    public boolean checkVerifyCode(String userId, String goodsId, String verifyCode) {
        // nothing
        return true;
    }


    /**
     * 生成动态url
     * @param userId
     * @param goodsId
     * @return
     */
    public String createPath(String userId, String goodsId) {
        String path = IdGenerate.nextId();
        // 使用redis的hash结构存储动态动态path
        redisTemplate.opsForHash().put(SecondKillConstatns.second_kill_url,userId+"_"+goodsId, path);
        return path;
    }
    /**
     * 检查动态url
     * @param userId
     * @param goodsId
     * @param path
     * @return
     */
    public boolean checkPath(String userId, String goodsId, String path) {
        if (userId==null || goodsId == null) {
            return false;
        }
        String redisPath = (String) redisTemplate.opsForHash().get(SecondKillConstatns.second_kill_url,userId+"_"+goodsId);
        if (redisPath==null) {
            return false;
        }else {
            return redisPath.equals(path);
        }
    }

    /**
     * 获取用户秒杀到的订单信息
     * @param userId
     * @param goodsId
     * @return
     */
    public Order getByUserIdWithGoodsId(String userId, String goodsId) {
        HashOperations<String,String,Order> operations = redisTemplate.opsForHash();
        return operations.get(SecondKillConstatns.second_kill_user_order,userId+"_"+goodsId);
    }

    /**
     * 减库存 下订单 写入秒杀订单
     * @param userId
     * @param goods
     * @return
     */
    @Transactional(readOnly = false)
    public Order realDoBuyGoods(String userId, Goods goods) {
        //减库存
        boolean success = this.reduceStock(goods);
        if(success) {
            //下订单
            Order order = orderService.createOrder(userId, goods);
            //将秒杀的用户商品订单存到redis中
            redisTemplate.opsForHash().putIfAbsent(SecondKillConstatns.second_kill_user_order, userId + "_" + goods.getId(), order);
            return order;
        }else {
            //记录出现的异常
            setGoodsOver(goods.getId());
            return null;
        }
    }

    /**
     * TODO 超卖：异常数据处理
     * 标识已经卖完了
     * @param goodsId
     */
    private void setGoodsOver(String goodsId) {
        redisTemplate.opsForHash().put(SecondKillConstatns.second_kill_over, goodsId, true);
    }

    /**
     * 判断商品是否已经卖完
     * @param goodsId
     */
    private boolean getGoodsOver(String goodsId) {
        boolean isExist = redisTemplate.opsForHash().hasKey(SecondKillConstatns.second_kill_over, goodsId);
        if(isExist){
            return (boolean)redisTemplate.opsForHash().get(SecondKillConstatns.second_kill_over, goodsId);
        }else{
            return false;
        }
    }

    @Transactional(readOnly = false)
    public boolean reduceStock(Goods goods) {
        long count = this.baseMapper.reduceStock(goods);
        return count > 0;
    }

    /**
     * 查询用户是否秒杀到
     * @param userId
     * @param goodsId
     * @return
     */
    public String getSecondKillResult(String userId, String goodsId) {
        //判断是否秒杀到了
        Order order = this.getByUserIdWithGoodsId(userId, goodsId);
        if(order != null) {
            //秒杀成功
            return order.getId();
        }else {
            boolean isOver = getGoodsOver(goodsId);
            if(isOver) {
                //卖完了
                return "-1";
            }else {
                //排队中
                return "0";
            }
        }
    }


}
